package controllers;

import java.io.File;
import java.util.LinkedList;
import java.util.List;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import controllers.Secure.Security;

import models.AbstractProfile;
import models.SocialProfile;
import models.User;
import play.data.validation.Required;
import play.db.jpa.GenericModel;
import play.db.jpa.JPABase;
import play.libs.WS;
import play.mvc.Controller;
import play.mvc.Http;
import play.mvc.With;

@With(Secure.class)
public class AbstractProfiles extends CRUD
{
	/**
	 * This method is used to delete an abstract profile of a user and all of
	 * the orphan children of this abstract profile, i.e. the social profiles,
	 * as well
	 * 
	 * @author Rania Said
	 * @param profile
	 *            : String profile which is the name of the abstract profile
	 *            that the user would like to delete
	 */
	public static void deleteIdentity(@Required String profile)
	{
		System.out.println("Running in AbstractProfiles.deleteIdentity method");

		User u = Users.getCurrentUser();
		if (u == null)
		{
			try
			{
				Secure.login();
			}
			catch (Throwable e)
			{

			}
		}
		else
		{
			if (validation.hasErrors())
			{
				flash.error("Oops, something went wrong!");
			}
			else
			{
				for (int i = 0; i < u.abstractProfileList.size(); i++)
				{
					if (u.abstractProfileList.get(i).name.equals(profile))
					{
						u.abstractProfileList.remove(i).delete();
						u.save();
						System.out
								.println("Number of AbstractProfiles for this user after deletion: "
										+ u.abstractProfileList.size());
						List<JPABase> pp = SocialProfile.findAll();
						System.out
								.println("Total Number of Social Profiles after deletion: "
										+ pp.size());
						break;
					}
				}
			}
			redirect("AbstractProfiles.manageIdentities");
		}
	}

	/**
	 * This method renders the view of AbstractProfiles.manageIdentities to
	 * allow the user to view his/her abstract profiles and provides the user
	 * with the option to manage them.
	 * 
	 * @author Rania Said
	 */
	public static void manageIdentities()
	{
		System.out.println("Running in "
				+ "AbstractProfiles.manageIdentities method");

		User u = Users.getCurrentUser();
		if (u == null)
		{
			try
			{
				Secure.login();
			}
			catch (Throwable e)
			{

			}
		}
		else
		{
			int num = u.abstractProfileList.size();
			List<AbstractProfile> identityList = u.abstractProfileList;
			int identityListSize = identityList.size() - 1;
			System.out.println("Number of AbstractProfiles for this user"
					+ identityListSize);
			render(num, identityList, identityListSize);
		}

	}

	/**
	 * This method renders the view of AbstractProfiles.manageIdentity to allow
	 * the user to manage a specific abstract profile.
	 * 
	 * @author Rania Said
	 * @param profile
	 *            : String profile which is the name of the abstract profile
	 *            that the user would like to manage
	 */
	public static void manageIdentity(@Required String profile)
	{
		System.out.println("Running in AbstractProfiles.manageIdentity method");

		User u = Users.getCurrentUser();
		if (u == null)
		{
			try
			{
				Secure.login();
			}
			catch (Throwable e)
			{

			}
		}
		else
		{
			if (validation.hasErrors())
			{
				flash.error("Oops, something went wrong!");
				redirect("AbstractProfiles.manageIdentities");
			}
			else
			{
				for (int i = 0; i < u.abstractProfileList.size(); i++)
				{
					if (u.abstractProfileList.get(i).name.equals(profile))
					{
						int num = u.abstractProfileList.get(i).profileList
								.size();
						List<SocialProfile> profileList = u.abstractProfileList
								.get(i).profileList;
						int profileListSize = profileList.size() - 1;
						String abstractProfile = profile;

						List<String> statusMsgs = SocialProfile
								.manageStatus((AbstractProfile) u.abstractProfileList
										.get(i));
						render(num, profileList, profileListSize,
								abstractProfile, statusMsgs);
						break;
					}
				}
			}
		}
	}

	/**
	 * This method render the view of AbstractProfiles.manageProfilePic
	 * 
	 * @author Rania Said
	 */
	public static void manageProfilePic()
	{
		render();
	}

	/**
	 * This method renders the view of AbstractProfiles.createIdentiy for the
	 * user to input some data and create a new abstract profile
	 */
	public static void createIdentity()
	{
		System.out.println("Running in AbstractProfiles.createIdentity method");
		User u = Users.getCurrentUser();
		if (u == null)
		{
			try
			{
				Secure.login();
			}
			catch (Throwable e)
			{

			}
		}
		else
		{
			String username = u.username;
			int num = u.abstractProfileList.size();
			render(username, num);
		}
	}

	/**
	 * This method creates a new abstract profile after the user enters some
	 * input in the previous page AbstractProfiles.createIdentity, and displays
	 * it for the user
	 * 
	 * @author Rania Said
	 * @param name
	 *            : String name which is the name of the new abstract profile
	 *            that the user wants to create
	 */
	public static void identityCreation(@Required String name)
	{
		User u = Users.getCurrentUser();
		if (u == null)
		{
			try
			{
				Secure.login();
			}
			catch (Throwable e)
			{

			}
		}
		else
		{
			if (validation.hasErrors())
			{
				flash.error("Oops, something went wrong!");
				createIdentity();
			}
			else
			{
				for (int i = 0; i < u.abstractProfileList.size(); i++)
				{
					if (u.abstractProfileList.get(i).name.equals(name))
					{
						flash.error("Oops, This identity already exists!");
						createIdentity();
					}
				}

				List<SocialProfile> p1 = new LinkedList<SocialProfile>();
				AbstractProfile prof = new AbstractProfile(name, p1, u);
				u.abstractProfileList.add(prof);
				u.save();
				redirect("AbstractProfiles.manageIdentities");
			}
		}
	}

	/**
	 * This method calls SocialProfiles.auth() to connect an OSN account to this
	 * AbstractProfile
	 * 
	 * @author Rania Said
	 * @param profileName
	 */
	public static void connectProfile(@Required String profileName)
	{
		System.out.println("Running in "
				+ "AbstractProfiles.connectProfile method");
		User u = Users.getCurrentUser();
		if (u == null)
		{
			try
			{
				Secure.login();
			}
			catch (Throwable e)
			{

			}
		}
		else
		{
			if (validation.hasErrors())
			{
				flash.error("Oops, something went wrong!");
				redirect("AbstractProfiles.manageIdentities");
			}
			else
			{
				for (int i = 0; i < u.abstractProfileList.size(); i++)
				{
					if (u.abstractProfileList.get(i).name.equals(profileName))
					{
						u.abstractProfileList.get(i).inConnection = true;
						u.save();
						SocialProfiles.auth();
						break;
					}
				}
			}
		}
	}

	/**
	 * This method runs the linkability and redundency module. It is added as a
	 * part of the future work of this project.
	 * 
	 * @param response
	 * @param abstractProfile
	 */
	public static void checkFacebook(JsonObject response,
			AbstractProfile abstractProfile)
	{
		User u = Users.getCurrentUser();
		if (u == null)
		{
			try
			{
				Secure.login();
			}
			catch (Throwable e)
			{

			}
		}
		else
		{
			if (response != null)
			{// redundency and linkability module
				String status = response.get("status").getAsString();
				long uID = response.getAsJsonObject("authResponse")
						.get("userID").getAsLong();

				if (status == "connected")
				{
					if (u.checkInsertionSame(abstractProfile, uID))
					{
						flash.error("Redundent");
						AbstractProfiles.manageIdentity(abstractProfile.name);
					}
				}
				else
				{
					if (status == "not_authorized")
					{
						// This account have never been connected before
						AbstractProfiles.connectProfile(abstractProfile.name);
					}
					else
					{
						// display a log in notification
						flash.error("Oops");
						AbstractProfiles.manageIdentity(abstractProfile.name);
					}
				}
			}
		}
	}

	public static void uploadPhoto()
	{

	}

}